iT邦幫忙

2024 iThome 鐵人賽

DAY 28
0
Odoo

30天就算 0 基礎,也能使用 GenAI 創造簡單的 Odoo 模組應用系列 第 28

【Day28】修復 GenAI 的幻覺 及 調整 Form View 上按鈕的位置

  • 分享至 

  • xImage
  •  

今天除了要修正上篇的 GenAI 幻覺外,也會進行實作上常需要調整圖視的擺放及順序,GenAI 可以很快幫上忙,只要你清楚圖示上的資料是在 XML 的哪一段。

接著會發現昨天的程式是有問題的,這也是大名鼎鼎 GenAI 的幻覺案例,但只要能確定問題出在哪 (錯誤訊息如下),GenAI 就能很容易解決,此時也別忘了要指定版本。

昨天的錯誤訊息,我們大致判斷出是最後的 Search View 有問題

Failed to load registry
Traceback (most recent call last):
  File "/home/odoo/src/odoo/odoo/modules/registry.py", line 114, in new
    odoo.modules.load_modules(registry, force_demo, status, update_module)
  ....
  File "/home/odoo/src/odoo/odoo/tools/convert.py", line 567, in _tag_root
    raise ParseError(msg) from None  # Restart with "--log-handler odoo.tools.convert:DEBUG" for complete traceback
odoo.tools.convert.ParseError: while parsing /home/odoo/src/user/library/views/book_views.xml:48
Invalid view library.books.search definition in library/views/book_views.xml

View error context:
'-no context-'

文章結構

  • GenAI 的幻覺:Search View 的 <filter> <group> 出問題
  • 用 GenAI 將 check_isbn 按鈕,從 Footer 改到 Header

GenAI 的幻覺:Search View 的 <filter> <group> 出問題

GenAI 提問

"""
#books.py
from odoo import models, fields, api
from odoo.exceptions import ValidationError

class Books(models.Model):
    _name = 'library.books'
    _description = 'Library Books'

    name = fields.Char(string='Book Name', required=True)
    isbn = fields.Char(string='ISBN')
    book_type = fields.Selection([
        ('paper', 'Paper'),
        ('ebook', 'E-Book'),
        ('other', 'Other')],
        string='Book Type', default='paper')
    description = fields.Text(string='Description')
    stock = fields.Integer(string='Stock')
    price_twd = fields.Float(string='Price (TWD)')
    average_rating = fields.Float(string='Average Rating', digits=(2, 2))
    publish_date = fields.Date(string='Publish Date')
    last_rent_date = fields.Datetime(string='Last Rent Date')
    rentable = fields.Boolean(string='Rentable', default=True)
    cover_image = fields.Binary(string='Cover Image')

    @api.model
    def is_valid_isbn(self, isbn):
        """簡單的 ISBN 驗證方法,支援 ISBN-10 和 ISBN-13"""
        isbn = isbn.replace('-', '').replace(' ', '')
        if len(isbn) == 10:
            total = sum((10 - i) * int(x) for i, x in enumerate(isbn[:9])) + (10 if isbn[-1] == 'X' else int(isbn[-1]))
            return total % 11 == 0
        elif len(isbn) == 13:
            total = sum(int(x) * (3 if i % 2 else 1) for i, x in enumerate(isbn))
            return total % 10 == 0
        return False

    def check_isbn(self):
        """檢查 ISBN,並在無效時拋出錯誤"""
        if not self.isbn:
            raise ValidationError("ISBN 欄位不能為空。")
        if not self.is_valid_isbn(self.isbn):
            raise ValidationError("輸入的 ISBN 無效,請檢查後再試。")
        return True

#book_views.xml
<odoo>
    <record id="view_book_form" model="ir.ui.view">
        <field name="name">library.books.form</field>
        <field name="model">library.books</field>
        <field name="arch" type="xml">
            <form string="Book">
                <sheet>
                    <group>
                        <field name="name"/>
                        <field name="isbn"/>
                        <field name="book_type"/>
                        <field name="description"/>
                        <field name="stock"/>
                        <field name="price_twd"/>
                        <field name="average_rating"/>
                        <field name="publish_date"/>
                        <field name="last_rent_date"/>
                        <field name="rentable"/>
                        <field name="cover_image" widget="image"/>
                    </group>
                    <footer>
                        <button name="check_isbn" string="檢查 ISBN" type="object" class="btn-primary"/>
                    </footer>
                </sheet>
            </form>
        </field>
    </record>

    <record id="view_book_tree" model="ir.ui.view">
        <field name="name">library.books.tree</field>
        <field name="model">library.books</field>
        <field name="arch" type="xml">
            <tree string="Books">
                <field name="name"/>
                <field name="isbn"/>
                <field name="book_type"/>
                <field name="stock"/>
                <field name="price_twd"/>
                <field name="average_rating"/>
                <field name="publish_date"/>
                <field name="last_rent_date"/>
                <field name="rentable"/>
            </tree>
        </field>
    </record>

    <!-- 新增 search view -->
    <record id="view_book_search" model="ir.ui.view">
        <field name="name">library.books.search</field>
        <field name="model">library.books</field>
        <field name="arch" type="xml">
            <search string="Search Books">
                <field name="name" string="Book Name"/>
                <field name="isbn" string="ISBN"/>
                <field name="book_type" string="Book Type"/>
                <field name="stock" string="Stock"/>
                <filter name="filter_rentable" string="Rentable" domain="[('rentable', '=', True)]"/>
                <filter name="filter_not_rentable" string="Not Rentable" domain="[('rentable', '=', False)]"/>
                <group expand="0" string="Group By"> 
                    <filter string="Book Type" group_by="book_type"/>
                    <filter string="Rentable" group_by="rentable"/>
                </group> 
            </search>
        </field>
    </record>
</odoo>
"""

                <group expand="0" string="Group By"> 
                    <filter string="Book Type" group_by="book_type"/>
                    <filter string="Rentable" group_by="rentable"/>
                </group>

有問題,請用 Odoo17 語法修正

GenAI 回答

Odoo 17 引入了一些新的語法變更,特別是在檢視文件(views)中,以下是需要修正的部分:

Group By Filters: 在 Odoo 17 中,<group> 和 <filter> 元素已經有了一些改變。group_by 參數應該直接放在 <filter> 元素內,並且需要確保用法符合最新語法。

<footer> 位置: 為了更好地控制按鈕,建議將 <footer> 放在 <form> 標籤的外部結束處。

以下是修正後的代碼,符合 Odoo 17 的語法:

<odoo>
    <record id="view_book_form" model="ir.ui.view">
        <field name="name">library.books.form</field>
        <field name="model">library.books</field>
        <field name="arch" type="xml">
            <form string="Book">
                <sheet>
                    <group>
                        <field name="name"/>
                        <field name="isbn"/>
                        <field name="book_type"/>
                        <field name="description"/>
                        <field name="stock"/>
                        <field name="price_twd"/>
                        <field name="average_rating"/>
                        <field name="publish_date"/>
                        <field name="last_rent_date"/>
                        <field name="rentable"/>
                        <field name="cover_image" widget="image"/>
                    </group>
                </sheet>
                <footer>
                    <button name="check_isbn" string="檢查 ISBN" type="object" class="btn-primary"/>
                </footer>
            </form>
        </field>
    </record>

    <record id="view_book_tree" model="ir.ui.view">
        <field name="name">library.books.tree</field>
        <field name="model">library.books</field>
        <field name="arch" type="xml">
            <tree string="Books">
                <field name="name"/>
                <field name="isbn"/>
                <field name="book_type"/>
                <field name="stock"/>
                <field name="price_twd"/>
                <field name="average_rating"/>
                <field name="publish_date"/>
                <field name="last_rent_date"/>
                <field name="rentable"/>
            </tree>
        </field>
    </record>

    <!-- 新增 search view -->
    <record id="view_book_search" model="ir.ui.view">
        <field name="name">library.books.search</field>
        <field name="model">library.books</field>
        <field name="arch" type="xml">
            <search string="Search Books">
                <field name="name" string="Book Name"/>
                <field name="isbn" string="ISBN"/>
                <field name="book_type" string="Book Type"/>
                <field name="stock" string="Stock"/>
                <filter name="filter_rentable" string="Rentable" domain="[('rentable', '=', True)]"/>
                <filter name="filter_not_rentable" string="Not Rentable" domain="[('rentable', '=', False)]"/>
                <!-- 修正 group by 的語法 -->
                <group>
                    <filter string="Book Type" context="{'group_by':'book_type'}"/>
                    <filter string="Rentable" context="{'group_by':'rentable'}"/>
                </group>
            </search>
        </field>
    </record>
</odoo>

主要修改點:
Group By 語法修正: 在 和 元素中,已經更新語法為使用 context="{'group_by':'field_name'}"。

用 GenAI 將 check_isbn 按鈕,從 Footer 改到 Header

GenAI 提問

<footer>
    <button name="check_isbn" string="檢查 ISBN" type="object" class="btn-primary"/>
</footer>

請將上面這段的 check_isbn button,從 footer 改成 header

GenAI 回答

要將 check_isbn 按鈕從 移動到 ,可以直接將按鈕標籤放在表單的 元素內,這樣按鈕會顯示在頁面的頂部而非底部。

以下是修改後的代碼:

<odoo>
    <record id="view_book_form" model="ir.ui.view">
        <field name="name">library.books.form</field>
        <field name="model">library.books</field>
        <field name="arch" type="xml">
            <form string="Book">
                <header>
                    <button name="check_isbn" string="檢查 ISBN" type="object" class="btn-primary"/>
                </header>
                <sheet>
                    <group>
                        <field name="name"/>
                        <field name="isbn"/>
                        <field name="book_type"/>
                        <field name="description"/>
                        <field name="stock"/>
                        <field name="price_twd"/>
                        <field name="average_rating"/>
                        <field name="publish_date"/>
                        <field name="last_rent_date"/>
                        <field name="rentable"/>
                        <field name="cover_image" widget="image"/>
                    </group>
                </sheet>
            </form>
        </field>
    </record>

    <record id="view_book_tree" model="ir.ui.view">
        <field name="name">library.books.tree</field>
        <field name="model">library.books</field>
        <field name="arch" type="xml">
            <tree string="Books">
                <field name="name"/>
                <field name="isbn"/>
                <field name="book_type"/>
                <field name="stock"/>
                <field name="price_twd"/>
                <field name="average_rating"/>
                <field name="publish_date"/>
                <field name="last_rent_date"/>
                <field name="rentable"/>
            </tree>
        </field>
    </record>

    <!-- 新增 search view -->
    <record id="view_book_search" model="ir.ui.view">
        <field name="name">library.books.search</field>
        <field name="model">library.books</field>
        <field name="arch" type="xml">
            <search string="Search Books">
                <field name="name" string="Book Name"/>
                <field name="isbn" string="ISBN"/>
                <field name="book_type" string="Book Type"/>
                <field name="stock" string="Stock"/>
                <filter name="filter_rentable" string="Rentable" domain="[('rentable', '=', True)]"/>
                <filter name="filter_not_rentable" string="Not Rentable" domain="[('rentable', '=', False)]"/>
                <!-- 修正 group by 的語法 -->
                <group>
                    <filter string="Book Type" context="{'group_by':'book_type'}"/>
                    <filter string="Rentable" context="{'group_by':'rentable'}"/>
                </group>
            </search>
        </field>
    </record>
</odoo>

修改後的部分:
<header>: 按鈕已移動到 <header> 元素中,這樣會顯示在表單頁面的頂部。


上一篇
【Day27】GenAI 擴充原有功能:ISBN 驗證 和 預設搜尋選項
下一篇
【Day29】回顧 GenAI 創造及擴充圖書館模組的過程及反思
系列文
30天就算 0 基礎,也能使用 GenAI 創造簡單的 Odoo 模組應用30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言